/**
 * weapp-js v2.2.3(2022-4-26)
 * https://codeup.aliyun.com/motigo/motigo/weapp_base
 * Copyright@ 2022 Motigo, Inc.
 * 
 */
import BaseRequest from './base_request.js';
import Request from './request.js';
import ui from './ui.js';
import Callback from './utils/callback.js';

class Session extends Callback {
    constructor() {
        super();
        this.id = ''; // sessionId: wapp_base自定义的id
        this.appid = '';
        this.user = {
            openid: null,
            unionid: null,
            nickName: null,
            avatarUrl: null,
            gender: null,
            country: null,
            city: null,
            province: null,
            language: null,
        };
        this._ready = false;
    }
    /**
     * 初始化，在app的onLaunch里面调用
     * 已弃用
     */
    init(appid, login) {
        this.appid = appid;
        // this._clearUser();
        // return new Promise((resolve, reject) => {
        //     if (login) {
        //         this._sessionLogin().then(data => {
        //             this._ready = true;
        //             resolve(data);
        //         }, err => {
        //             reject(err);
        //         })
        //     } else {
        //         this._ready = true;
        //         resolve();
        //     }
        // });
    }
    /* 检查是否ready */
    // check() {
    //     return new Promise((resolve) => {
    //         if (this._ready) {
    //             resolve();
    //         } else {
    //             let start = Date.now();
    //             let check_timer = setInterval(() => {
    //                 if (this._ready || Date.now() - start > 5 * 1000) {
    //                     clearInterval(check_timer);
    //                     resolve();
    //                 }
    //             }, 50);
    //         }
    //     });
    // }
    // 能够获取nickName、avatarUrl、gender等信息的登录接口，如果绑定了开放平台，也可以获取到unionid
    login(opts = {}) {
        let hardMode = opts.hardMode || false;
        let useUILogin = typeof opts.ui === 'boolean' ? opts.ui : false; // 未登录时是否自动弹出登录框
        this._sessionLogin(hardMode).then(
            () => {
                if (useUILogin) {
                    // 采用登陆框获取用户头像昵称
                    if (this.user.openid && (this.user.avatarUrl || this.user.nickName)) {
                        this.success(opts, this.user);
                    } else {
                        ui.login(opts).then(
                            res => {
                                console.log('ui login res');
                                console.log(res);
                                this._setSessionCache(res);
                                this.success(opts, res);
                            },
                            err => {
                                console.error('login fail, err:', err);
                                this._clearSessionCache();
                                // reject()
                                this.fail(opts, err);
                            }
                        );
                    }
                } else {
                    if (this.user.openid) {
                        this.success(opts, this.user);
                    } else {
                        this.fail(opts, 'user not login');
                    }
                }
            },
            err => {
                err;
                // reject('session login fail');
                this.fail(opts, 'session login fail');
            }
        );
    }
    _decrpytUserInfo(encryptData = '', iv = '') {
        console.log('decrpytUserInfo');
        console.log(encryptData, iv);
        return new Promise((resolve, reject) => {
            if (this.appid && encryptData && iv) {
                BaseRequest.post(`/decrypy/userinfo/${this.appid}`, {
                    encrypted_data: encryptData,
                    session_id: this.id,
                    iv: iv
                }).then(
                    data => {
                        // data.sessionId = this.id;
                        const sessionData = {
                            sessionId: this.id,
                            openid: data.openId,
                            unionid: data.unionId,
                            nickName: data.nickName,
                            gender: data.gender,
                            avatarUrl: data.avatarUrl,
                            country: data.country,
                            city: data.city,
                            province: data.province,
                            language: data.language
                        };
                        this._setSessionCache(sessionData);
                        resolve(sessionData);
                    },
                    err => {
                        console.error('decrypt user info fail, err:', err);
                        if (err && err.ret == -3) {
                            // invalid session
                            this._clearSessionCache();
                        }
                        reject(err ? err.msg : '');
                    }
                );
            } else {
                reject('invalid param');
            }
        });
    }
    decrpytUserPhone(opts) {
        let { encryptedData, iv } = opts;
        if (this.appid && encryptedData && iv) {
            BaseRequest.post(`/phone/decrypt/${this.appid}`, {
                encryptedData: encryptedData,
                iv: iv
            }).then(
                data => {
                    // data.sessionId = this.id;
                    const phoneData = {
                        userPhone: data.phoneNumber,
                        purePhone: data.purePhoneNumber,
                        countryCode: data.countryCode
                    };
                    // this._setSessionCache(phoneData);
                    // resolve(phoneData);
                    this.success(opts, phoneData);
                },
                err => {
                    console.error('decrypt user phone fail, err:', err);
                    if (err && err.ret == -3) {
                        // invalid session
                        this._clearSessionCache();
                    }
                    // reject(err ? (err.msg) : '');
                    this.fail(opts, err ? err.msg || '' : '');
                }
            );
        } else {
            // reject('invalid param');
            this.fail(opts, 'invalid param');
        }
    }
    // 登录，会检查session的有效性，无效则使用wx.login登录并从weapp_base中获得openid/unionid等信息
    _sessionLogin(hardMode) {
        return new Promise((resolve, reject) => {
            this._checkSession(hardMode).then(
                data => {
                    resolve(data);
                },
                () => {
                    this._clearUser();
                    wx.login({
                        timeout: 3000,
                        success: res => {
                            BaseRequest.post(`/auth/session/${this.appid}`, {
                                code: res.code
                            })
                                .then(
                                    data => {
                                        this._setSessionCache(data);
                                        resolve(data);
                                    }

                                    // (err) => {
                                    //     console.error(
                                    //         'baseRequest fail, err:',
                                    //         err
                                    //     );
                                    //     reject(err);
                                    // }
                                )
                                .catch(err => {
                                    console.log(err);
                                    reject(err);
                                });
                        },
                        fail(res) {
                            console.error('wx.login fail! err:', res);
                            reject(res);
                        }
                    });
                }
            );
        });
    }
    _checkSession(hardMode) {
        return new Promise((resolve, reject) => {
            wx.checkSession({
                success: () => {
                    this._getSessionCache(hardMode).then(
                        data => {
                            resolve(data);
                        },
                        err => {
                            // err;
                            reject(err);
                        }
                    );
                },
                fail: () => {
                    reject();
                }
            });
        });
    }
    _getSessionCache(hardMode) {
        hardMode = hardMode == undefined ? false : hardMode;

        return new Promise((resolve, reject) => {
            wx.getStorage({
                key: '__session__',
                success: res => {
                    console.log('_getSessionCache success');
                    console.log(res);
                    try {
                        const sessionData = JSON.parse(res.data);
                        console.log(sessionData);
                        console.log(sessionData.sessionId);
                        sessionData.createTime = sessionData.createTime || 1;
                        let ttl = hardMode ? 2 * 60 : 24 * 3600; // hard模式session过期时间2分钟

                        if (Date.now() / 1000.0 - sessionData.createTime < ttl) {
                            // 本地缓存的信息，24小时过期
                            this.id = sessionData.sessionId;
                            const keys = [
                                'openid',
                                'unionid',
                                'nickName',
                                'avatarUrl',
                                'gender',
                                'country',
                                'city',
                                'province',
                                'language',
                            ];

                            keys.forEach(k => {
                                this.user[k] = sessionData[k];
                            });
                            BaseRequest.updateSession(
                                this.id,
                                this.appid,
                                this.user.openid,
                                this.user.unionid
                            );
                            Request.updateSession(
                                this.id,
                                this.appid,
                                this.user.openid,
                                this.user.unionid
                            );

                            resolve(sessionData);
                        } else {
                            reject();
                        }
                    } catch (e) {
                        e;
                        reject();
                    }
                },
                fail: () => {
                    reject();
                }
            });
        });
    }
    _setSessionCache(sessionData) {
        console.log('_setSessionCache');
        console.log(sessionData);
        console.log(this.id);
        if (sessionData) {
            let sessionId = sessionData.session_id || sessionData.sessionId;
            this.id = sessionId || this.id;
            sessionData.createTime = parseInt(Date.now() / 1000.0);

            const keys = [
                'openid',
                'unionid',
                'nickName',
                'avatarUrl',
                'gender',
                'country',
                'city',
                'province',
                'language'
            ];

            keys.forEach(k => {
                this.user[k] = k in sessionData ? sessionData[k] : this.user[k] || null;
            });

            wx.setStorage({
                key: '__session__',
                data: JSON.stringify({
                    ...sessionData,
                    ...this.user,
                    sessionId: this.id
                })
            });

            BaseRequest.updateSession(this.id, this.appid, this.user.openid, this.user.unionid);
            Request.updateSession(this.id, this.appid, this.user.openid, this.user.unionid);
        }
    }
    _clearSessionCache() {
        wx.removeStorage({
            key: '__session__'
        });
    }
    _clearUser() {
        for (let k in this.user) {
            this.user[k] = null;
        }
    }
    __updateUserData(sessionData) {
        USER_KEYS.forEach(k => {
            if (k in sessionData) {
                this.user[k] = sessionData[k];
            }
        });

        BaseRequest._update_session(this.id, this.appid, this.user.openid, this.user.unionid);
        request._update_session(this.id, this.appid, this.user.openid, this.user.unionid);
    }
}

export default new Session();
